package vip.ola.service.impl.code;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import vip.ola.core.common.Exception.ServiceException;
import vip.ola.core.common.util.MyLog;
import vip.ola.core.common.util.RedisUtil;
import vip.ola.core.entity.code.CodeInfo;
import vip.ola.core.service.ISysConfigService;
import vip.ola.core.service.code.CodeInfoService;
import vip.ola.service.dao.mapper.code.CodeInfoMapper;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import static vip.ola.core.common.constant.CacheKey.HALF_HOURS;
import static vip.ola.core.common.constant.CacheKey.QR_CODE;
import static vip.ola.core.common.constant.CodeConstant.CODE_STATUS_OK;
import static vip.ola.core.common.constant.CodeConstant.ORDER_STATUS_EXPIRED;
import static vip.ola.core.common.constant.Constant.SYS_CONFIG_CODE;
import static vip.ola.core.common.constant.RetEnum.CODE_QRCODE_UPDATE_ERROR;
import static vip.ola.core.common.constant.SysConfigConstant.*;

/**
 * <p>
 * 二维码信息 服务实现类
 * </p>
 *
 * @author faker
 * @since 2020-03-25
 */
@Service(interfaceClass = CodeInfoService.class, version = "1.0.0")
@Transactional
public class CodeInfoServiceImpl extends ServiceImpl<CodeInfoMapper, CodeInfo> implements CodeInfoService {

    private final MyLog logger = MyLog.getLog(this.getClass());

    @Value("${qr.preview-url}")
    private String qrPreviewUrl;

    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private RedisUtil redisUtil;


    @Override
    public IPage<CodeInfo> list(int currentPage, int pageSize, CodeInfo codeInfo) {
        Page page = new Page(currentPage, pageSize);
        return baseMapper.list(page, codeInfo);
    }

    public CodeInfo getCacheById(long id) {
        return redisUtil.get(QR_CODE + id, () -> {
            CodeInfo codeInfo = baseMapper.selectById(id);
            codeInfo.setCodePath(qrPreviewUrl + codeInfo.getCodePath());
            return codeInfo;
        }, CodeInfo.class, HALF_HOURS);
    }

    public String getCodeUrlByCache(long id) {
        CodeInfo codeInfo = getCacheById(id);
        return codeInfo.getCodePath();
    }

    @Override
    public CodeInfo getByCodeInfo(CodeInfo codeInfo) {
        codeInfo = baseMapper.getByCodeInfo(codeInfo);
        if (codeInfo != null) {
            codeInfo.setCodePath(qrPreviewUrl + codeInfo.getCodePath());
        }
        return codeInfo;
    }

    @Override
    public CodeInfo getByCodeUrl(String codeUrl) {
        return baseMapper.getByCodeUrl(codeUrl);
    }

    @Override
    public boolean cleanCodeCollInfo(Long codeBusId, Long agentId, Long userId) {
        String sysValue = sysConfigService.getSysValue(SYS_CONFIG_CODE, CODE_WEIGHT);
        return SqlHelper.retBool(baseMapper.cleanCodeCollInfo(codeBusId, agentId, userId, Integer.parseInt(sysValue)));
    }

    @Override
    public void updateCodeCollInfo(long codeId, BigDecimal profit, Integer orderStatus, BigDecimal orderAmount) {
        String sysValue = sysConfigService.getSysValue(SYS_CONFIG_CODE, SUC_WEIGHT);
        int weight = Integer.parseInt(sysValue);
        if (ORDER_STATUS_EXPIRED.equals(orderStatus)) {
            weight = weight * 2;
        }
        String orderInterval = sysConfigService.getSysValue(SYS_CONFIG_CODE, QR_ORDER_INTERVAL);
        Integer interval = Optional.ofNullable(orderInterval).map(Integer::new).orElse(5);
        LocalDateTime nextTime = LocalDateTime.now().plusMinutes(interval);
        int row = baseMapper.updateCodeCollInfo(codeId, orderAmount, profit, weight, nextTime);
        if (row == 0) {
            throw new ServiceException(CODE_QRCODE_UPDATE_ERROR);
        }
    }

    @Override
    public boolean updateStatus(long codeId, int status) {
        CodeInfo codeInfo = new CodeInfo();
        codeInfo.setId(codeId);
        codeInfo.setStatus(status);
        if (CODE_STATUS_OK.equals(status)) {
            String sysValue = sysConfigService.getSysValue(SYS_CONFIG_CODE, CODE_WEIGHT);
            codeInfo.setWeight(Integer.valueOf(sysValue));
        }
        codeInfo.setUpdateTime(LocalDateTime.now());
        return updateById(codeInfo);
    }

    @Override
    public List<CodeInfo> getAvailableQrCode(Long codeBusId, Integer codeType, BigDecimal orderAmount, boolean needThirdId, int offset, int availableLimit) {
        return baseMapper.getAvailableQrCode(codeBusId, codeType, orderAmount, needThirdId, offset, availableLimit);
    }

    @Override
    public List<CodeInfo> getAvailableBestQrCode(Long codeBusId, Integer codeType, BigDecimal orderAmount, boolean needThirdId, int offset, int availableLimit) {
        return baseMapper.getAvailableBestQrCode(codeBusId, codeType, orderAmount, needThirdId, offset, availableLimit);
    }

    @Override
    public int updateCodeAgentRate(long agentId, BigDecimal rate) {
        return baseMapper.updateCodeAgentRate(agentId, rate);
    }

    @Override
    public int updateCodeBusRate(long codeBusId, BigDecimal rate) {
        return baseMapper.updateCodeBusRate(codeBusId, rate);
    }

    @Override
    public int updateFailWeight(List idList, int weight) {
        return baseMapper.updateFailWeight(idList, weight);
    }
}
